<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES6新增特性Proxy+Reflect</title>
</head>

<body>
    <script>
        const obj = {
            "id": "3494b47e-e7f5-4f08-a9db-ab698a76e350",
            "title": "CSS 实现固定表头表格",
            "cover": "https://wipi.oss-cn-shanghai.aliyuncs.com/2021-03-26/css-table.png",
            "summary": "几行 CSS 实现固定表头的表格。",
            "content": "通过 `position: sticky` 可以很容易实现固定表头的表格。\n\n```css\ntable {\n  width: 100%;\n  border-collapse: separate;\n  border-spacing: 0;\n}\n\ntable thead th {\n  position: sticky;\n  top: 0;\n  z-index: 1;\n  background: #fff;\n  border: 1px solid #000;\n}\n```\n\n| 项目        | 价格   |  数量  |\n| --------   | -----:  | :----:  |\n| 计算机     | ￥1600 |   5     |\n| 手机        |   ￥12   |   12   |\n| 管线        |    ￥$1    |  234  |\n| 计算机     | ￥1600 |   5     |\n| 手机        |   ￥12   |   12   |\n| 管线        |    ￥$1    |  234  |\n| 计算机     | ￥1600 |   5     |\n| 手机        |   ￥12   |   12   |\n| 管线        |    ￥$1    |  234  |\n| 计算机     | ￥1600 |   5     |\n| 手机        |   ￥12   |   12   |\n| 管线        |    ￥$1    |  234  |\n\n<iframe src=\"https://codesandbox.io/embed/dazzling-elgamal-o9nho?fontsize=14&hidenavigation=0&theme=dark\"\n     style=\"width:100%; height:420px; border:0; border-radius: 4px; overflow:hidden;\"\n     title=\"dazzling-elgamal-o9nho\"\n     allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n     sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n   ></iframe>",
            "html": "<p>通过 <code>position: sticky</code> 可以很容易实现固定表头的表格。</p>\n<pre><code class=\"css language-css\">table {\n  width: 100%;\n  border-collapse: separate;\n  border-spacing: 0;\n}\n\ntable thead th {\n  position: sticky;\n  top: 0;\n  z-index: 1;\n  background: #fff;\n  border: 1px solid #000;\n}\n</code></pre>\n<table>\n<thead>\n<tr>\n<th>项目</th>\n<th style=\"text-align:right;\">价格</th>\n<th style=\"text-align:center;\">数量</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>计算机</td>\n<td style=\"text-align:right;\">￥1600</td>\n<td style=\"text-align:center;\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td style=\"text-align:right;\">￥12</td>\n<td style=\"text-align:center;\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td style=\"text-align:right;\">￥$1</td>\n<td style=\"text-align:center;\">234</td>\n</tr>\n<tr>\n<td>计算机</td>\n<td style=\"text-align:right;\">￥1600</td>\n<td style=\"text-align:center;\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td style=\"text-align:right;\">￥12</td>\n<td style=\"text-align:center;\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td style=\"text-align:right;\">￥$1</td>\n<td style=\"text-align:center;\">234</td>\n</tr>\n<tr>\n<td>计算机</td>\n<td style=\"text-align:right;\">￥1600</td>\n<td style=\"text-align:center;\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td style=\"text-align:right;\">￥12</td>\n<td style=\"text-align:center;\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td style=\"text-align:right;\">￥$1</td>\n<td style=\"text-align:center;\">234</td>\n</tr>\n<tr>\n<td>计算机</td>\n<td style=\"text-align:right;\">￥1600</td>\n<td style=\"text-align:center;\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td style=\"text-align:right;\">￥12</td>\n<td style=\"text-align:center;\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td style=\"text-align:right;\">￥$1</td>\n<td style=\"text-align:center;\">234</td>\n</tr>\n</tbody>\n</table>\n<iframe src=\"https://codesandbox.io/embed/dazzling-elgamal-o9nho?fontsize=14&hidenavigation=0&theme=dark\"\n     style=\"width:100%; height:420px; border:0; border-radius: 4px; overflow:hidden;\"\n     title=\"dazzling-elgamal-o9nho\"\n     allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n     sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n   ></iframe>",
            "toc": "[]",
            "status": "publish",
            "views": 705,
            "likes": 70,
            "isRecommended": false,
            "needPassword": false,
            "isCommentable": true,
            "publishAt": "2021-03-25T18:43:48.000Z",
            "createAt": "2021-03-26T02:20:14.040Z",
            "updateAt": "2021-11-29T17:28:11.000Z",
            "tags": [],
            "category": null
        };
        /* 
        Proxy代理taregt,使用handle拦截处理默认行为
            get(target, propKey, receiver)：拦截对象属性的读取，比如proxy.foo和proxy['foo']。
            set(target, propKey, value, receiver)：拦截对象属性的设置，比如proxy.foo = v或proxy['foo'] = v，返回一个布尔值。
            has(target, propKey)：拦截propKey in proxy的操作，返回一个布尔值。
            deleteProperty(target, propKey)：拦截delete proxy[propKey]的操作，返回一个布尔值。
            ownKeys(target)：拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环，返回一个数组。该方法返回目标对象所有自身的属性的属性名，而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
            getOwnPropertyDescriptor(target, propKey)：拦截Object.getOwnPropertyDescriptor(proxy, propKey)，返回属性的描述对象。
            defineProperty(target, propKey, propDesc)：拦截Object.defineProperty(proxy, propKey, propDesc）、Object.defineProperties(proxy, propDescs)，返回一个布尔值。
            preventExtensions(target)：拦截Object.preventExtensions(proxy)，返回一个布尔值。
            getPrototypeOf(target)：拦截Object.getPrototypeOf(proxy)，返回一个对象。
            isExtensible(target)：拦截Object.isExtensible(proxy)，返回一个布尔值。
            setPrototypeOf(target, proto)：拦截Object.setPrototypeOf(proxy, proto)，返回一个布尔值。如果目标对象是函数，那么还有两种额外操作可以拦截。
            apply(target, object, args)：拦截 Proxy 实例作为函数调用的操作，比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
            construct(target, args)：拦截 Proxy 实例作为构造函数调用的操作，比如new proxy(...args)。
        *
        Reflect,反射拿到目标的默认行为
            get(target, propKey, receiver)：拦截对象属性的读取，比如proxy.foo和proxy['foo']。
            set(target, propKey, value, receiver)：拦截对象属性的设置，比如proxy.foo = v或proxy['foo'] = v，返回一个布尔值。
            has(target, propKey)：拦截propKey in proxy的操作，返回一个布尔值。
            deleteProperty(target, propKey)：拦截delete proxy[propKey]的操作，返回一个布尔值。
            ownKeys(target)：拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环，返回一个数组。该方法返回目标对象所有自身的属性的属性名，而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
            getOwnPropertyDescriptor(target, propKey)：拦截Object.getOwnPropertyDescriptor(proxy, propKey)，返回属性的描述对象。
            defineProperty(target, propKey, propDesc)：拦截Object.defineProperty(proxy, propKey, propDesc）、Object.defineProperties(proxy, propDescs)，返回一个布尔值。
            preventExtensions(target)：拦截Object.preventExtensions(proxy)，返回一个布尔值。
            getPrototypeOf(target)：拦截Object.getPrototypeOf(proxy)，返回一个对象。
            isExtensible(target)：拦截Object.isExtensible(proxy)，返回一个布尔值。
            setPrototypeOf(target, proto)：拦截Object.setPrototypeOf(proxy, proto)，返回一个布尔值。如果目标对象是函数，那么还有两种额外操作可以拦截。
            apply(target, object, args)：拦截 Proxy 实例作为函数调用的操作，比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
            construct(target, args)：拦截 Proxy 实例作为构造函数调用的操作，比如new proxy(...args)。
         */ 
        const p = new Proxy(obj, {
            get(target, key ,receiver){
                // console.log('arguments...', '劫持了obj的get方法');
                return Reflect.get(target, key, receiver);
            },
            set(target, key, value, receiver){
                // console.log('arguments...', arguments, '劫持了obj的set方法');
                return Reflect.set(target, key, value, receiver);
            }
        });

        /**
         * Set, 元素不重复的集合
         * WeakSet，每一个元素都必须是对象类型的数据集合
         * Map, key和value均可是任意类型的映射
         * WeakMap, key只能是对象，value是任意类型的映射
         */
        const arr = new Set([1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10]);
        console.log('arr...', arr);

        const weakSet = new WeakSet();
        const fn = function(){return 'i am a function'};
        weakSet.add({key: 1});
        weakSet.add(fn);
        // weakSet.add(2);
        console.log('weakSet...', weakSet, weakSet.has(fn));

        const map = new Map();
        const weakMap = new WeakMap();

    </script>
</body>

</html>